const { src, dest, parallel, series, watch } = require('gulp')
const del = require('del')
const browserSync = require('browser-sync')
const loadPlugin = require('gulp-load-plugins')

const plugin = loadPlugin()

const bs = browserSync.create()

const data = {
    menus: [
        {
            name: 'Home',
            icon: 'aperture',
            link: 'index.html'
        },
        {
            name: 'Features',
            link: 'features.html'
        },
        {
            name: 'About',
            link: 'about.html'
        },
        {
            name: 'Contact',
            link: '#',
            children: [
                {
                    name: 'Twitter',
                    link: 'https://twitter.com/w_zce'
                },
                {
                    name: 'About',
                    link: 'https://weibo.com/zceme'
                },
                {
                    name: 'divider'
                },
                {
                    name: 'About',
                    link: 'https://github.com/zce'
                }
            ]
        }
    ],
    pkg: require('./package.json'),
    date: new Date()
}

//清除任务依赖安装  yarn gulp del --dev
/**
 * 删除的废弃文件任务
 * @returns {Promise<string[]> | *}
 */
const clean = () => {
    return del(['dist', 'temp'])
}

//创建一个style的文件处理配置
/**
 * 样式编译的任务
 * @returns {*}
 */
const style = () => {

    //如果没有base参数的话 文件会被全部直接构建到dist目录下， 原本的目录结构就被丢失了
    //使用这个目录结构后会保存base的文件后面的所有目录结构
    //使用国base后 但是后缀名还没有转换 所以还需要将文件的后缀名转换了  这时就需要使用一个新的插件 gulp-plugin.sass
    //yarn add gulp-plugin.sass@4.1.0 --dev
    return src('src/assets/styles/*.scss', {base: 'src'})
        .pipe(plugin.sass({outputStyle: 'expanded'}))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true }))  //以流的方式推到浏览器 实现页面更新的效果
}

/**
 * 脚本编译的任务
 */
const script = () => {

    //script 文件流的写入
    //将ES6转化为普通函数
    //安装babel插件  yarn add gulp-plugin.babel @plugin.babel/core @plugin.babel/preset-env --dev
    return src('src/assets/scripts/*.js', { base: 'src'})
        .pipe(plugin.babel({ presets: ['@babel/preset-env'] }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true }))
}

//html模版文件的安装
// yarn add gulp-plugin.swig --dev
/**
 * html模版编译任务
 */
const page = () => {
    return src('src/*.html', { base: 'src' })
        //在里面添加data参数 用于在html模版文件输出
        .pipe(plugin.swig({ data, defaults: { cache: false } }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true }))
}

//进行image任务编译需要安装imagemin
// yarn add gulp-plugin.imagemin --dev
/**
 * 图片文件编译 图片压缩
 */
const image = () => {
    return src('src/assets/images/**', { base: 'src' })
        .pipe(plugin.imagemin())
        .pipe(dest('dist'))
}

/**
 * 字体文件编译
 */
const font = () => {
    return src('src/assets/fonts/**', { base: 'src' })
        .pipe(plugin.imagemin())
        .pipe(dest('dist'))
}

/**
 * 其他任务
 * @returns {*}
 */
const extra = () => {
    return src('public/**', { base: 'public' })
        .pipe(dest('dist'))
}

/**
 * 文件注释编译任务处理
 */
const useref = () => {
    return src('temp/*.html', { base: 'temp' })
        .pipe(plugin.useref({ searchPath: ['temp', '.'] }))
        .pipe(plugin.if(/\.js$/, plugin.uglify()))
        .pipe(plugin.if(/\.css$/, plugin.cleanCss()))
        // .pipe(plugin.if(/\.html$/, plugin.htmlmin()))  //html默认只是将空白字符压缩掉 如果需要将换行符进行压缩 还需要进行配置
        .pipe(plugin.if(/\.html$/, plugin.htmlmin({
            collapseWhitespace: true,
            minifyCSS: true,   //将html里的css文件进行压缩
            minifyJs: true,    //将html里的js文件进行压缩
        })))
        // .pipe(dest('dist'))  //也可以将构建后的文件放在另外的地方
        .pipe(dest('dist'))
}

/**
 * 服务器命令
 */
const serve = () => {
    watch('src/assets/styles/*.scss', style)
    watch('src/assets/scripts/*.js', script)
    watch('src/*.html', page)
    // watch('src/assets/images/**', image)
    // watch('src/assets/fonts/**', font)
    // watch('public/**', extra)
    watch([
        'src/assets/images/**',
        'src/assets/fonts/**',
        'public/**',
    ], bs.reload)   //reload 也可以理解为一个任务（本质为一个函数）

    // 初始化一个服务器的相关配置
    bs.init({
        notify: false,  //服务器链接状态提示 是否开启  false： 如果服务器启动或者页面刷新后不会提示链接信息了
        port: '2080',  //browser-async的端口
        // open: false,  //默认浏览器是否打开
        // files: 'dist/**',  //被browser-async监听过后的一个通配符   dist下面的所有文件  可以和bs.reload替换
        server: {
            //需要设置网站的根目录， 去告诉使用着这个目录为根目录
            baseDir: ['temp', 'src', 'public'],
            //用于配置页面的路由 如果网页里面有一些/node_moduls的话会将其指定为routers里面的路由
            //routers里面的配置的优先级高
            routes: {
                '/node_modules': 'node_modules'
            }
        }
    })

    //由于使用useref使目录打包的目录发生了改变（原来的打包目录： dist 现在的打包目录： release）
}

//三个任务需要全部执行
//执行异步任务
//src 下的文件构建
const compile = parallel(style, script, page)

//全部构建
const build =  series(
    clean,
    parallel(
        series(compile, useref),
        extra,
        image,
        font
    )
)

//开发服务
const develop = series(compile, serve)

module.exports = {
    clean,
    build,
    develop,
}
